/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include "PGLX.h"
#include "PGLXCtl.h"
#include "PGLXPpg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


IMPLEMENT_DYNCREATE(CPGLXCtrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CPGLXCtrl, COleControl)
	//{{AFX_MSG_MAP(CPGLXCtrl)
	// NOTE - ClassWizard will add and remove message map entries
	//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG_MAP
	ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
	ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CPGLXCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CPGLXCtrl)
	DISP_PROPERTY_NOTIFY(CPGLXCtrl, "XMLFile", m_sXMLFile, OnXMLFileChanged, VT_BSTR)
	DISP_PROPERTY_NOTIFY(CPGLXCtrl, "XMLString", m_sXMLString, OnXMLStringChanged, VT_BSTR)
	DISP_PROPERTY_NOTIFY(CPGLXCtrl, "XMLURL", m_sXMLURL, OnXMLURLChanged, VT_BSTR)
	DISP_PROPERTY_NOTIFY(CPGLXCtrl, "AutoZoom", m_bAutoZoom, OnAutoZoomChanged, VT_BOOL)
	DISP_FUNCTION(CPGLXCtrl, "Figure", Figure, VT_I4, VTS_NONE)
	DISP_FUNCTION(CPGLXCtrl, "SetCR", SetCR, VT_BOOL, VTS_I4)
	DISP_FUNCTION(CPGLXCtrl, "CloseAllFigures", CloseAllFigures, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CPGLXCtrl, "Divide", Divide, VT_EMPTY, VTS_I4 VTS_I2 VTS_I2)
	DISP_FUNCTION(CPGLXCtrl, "Get", Get, VT_BSTR, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "GetCR", GetCR, VT_I4, VTS_NONE)
	DISP_FUNCTION(CPGLXCtrl, "GetHelp", GetHelp, VT_BSTR, VTS_I4)
	DISP_FUNCTION(CPGLXCtrl, "GetParent", GetParent, VT_I4, VTS_I4)
	DISP_FUNCTION(CPGLXCtrl, "Histogram", Histogram, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "Plot", Plot, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "Legend", Legend, VT_I4, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "PlotLOD", PlotLOD, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT VTS_R4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "Title", Title, VT_EMPTY, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "XLabel", XLabel, VT_EMPTY, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "YLabel", YLabel, VT_EMPTY, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "RenderToFile", RenderToFile, VT_BOOL, VTS_I4 VTS_VARIANT VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "GetChild", GetChild, VT_I4, VTS_I4 VTS_I4)
	DISP_FUNCTION(CPGLXCtrl, "ClearRegion", ClearRegion, VT_EMPTY, VTS_I4)
	DISP_FUNCTION(CPGLXCtrl, "Set", Set, VT_EMPTY, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "OutOfChild", OutOfChild, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CPGLXCtrl, "SaveToXml", SaveToXml, VT_BOOL, VTS_I4 VTS_VARIANT VTS_I2)
	DISP_FUNCTION(CPGLXCtrl, "LoadFromXML", LoadFromXML, VT_BOOL, VTS_I4 VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "Stock", Stock, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "Scatter", Scatter, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT)
	DISP_FUNCTION(CPGLXCtrl, "ErrorBar", ErrorBar, VT_I4, VTS_I4 VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT)
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CPGLXCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CPGLXCtrl, COleControl)
	//{{AFX_EVENT_MAP(CPGLXCtrl)
	// NOTE - ClassWizard will add and remove event map entries
	//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CPGLXCtrl, 1)
	PROPPAGEID(CPGLXPropPage::guid)
END_PROPPAGEIDS(CPGLXCtrl)

/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CPGLXCtrl, "PGLX.PGLXCtrl.1",
	0x9a585713, 0x783b, 0x45fe, 0x90, 0x82, 0x72, 0x87, 0x6f, 0x3, 0x2f, 0x69)

/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CPGLXCtrl, _tlid, _wVerMajor, _wVerMinor)

/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DPGLX =
		{ 0xf8e0515a, 0x79f0, 0x4841, { 0xbe, 0xd1, 0x74, 0x4f, 0x25, 0xbb, 0xef, 0x6c } };
const IID BASED_CODE IID_DPGLXEvents =
		{ 0x8ed2f2a, 0xf83c, 0x42ef, { 0xb4, 0x11, 0x2b, 0xd0, 0x87, 0x69, 0xb1, 0xb8 } };



/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwPGLXOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CPGLXCtrl, IDS_PGLX, _dwPGLXOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::CPGLXCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CPGLXCtrl

BOOL CPGLXCtrl::CPGLXCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegInsertable | afxRegApartmentThreading to afxRegInsertable.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_PGLX,
			IDB_PGLX,
			afxRegInsertable | afxRegApartmentThreading,
			_dwPGLXOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}

/////////////////////////////////////////////////////////////////////////////
// Licensing strings

static const TCHAR BASED_CODE _szLicFileName[] = _T("");

static const WCHAR BASED_CODE _szLicString[] =
	L"";

/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::CPGLXCtrlFactory::VerifyUserLicense -
// Checks for existence of a user license

BOOL CPGLXCtrl::CPGLXCtrlFactory::VerifyUserLicense()
{
	return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
		_szLicString);
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::CPGLXCtrlFactory::GetLicenseKey -
// Returns a runtime licensing key

BOOL CPGLXCtrl::CPGLXCtrlFactory::GetLicenseKey(DWORD dwReserved,
	BSTR FAR* pbstrKey)
{
	if (pbstrKey == NULL)
		return FALSE;

	*pbstrKey = SysAllocString(_szLicString);
	return (*pbstrKey != NULL);
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::CPGLXCtrl - Constructor

CPGLXCtrl::CPGLXCtrl()
: m_bAutoZoom(TRUE)
{
	InitializeIIDs(&IID_DPGLX, &IID_DPGLXEvents);

	m_GDIpInitializer.Initialize();

	m_pRegion=CPGLRegionPtr(new CPGLRegion);
	if (m_pRegion)
		m_script.SetCR( m_pRegion->GetID());
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::~CPGLXCtrl - Destructor

CPGLXCtrl::~CPGLXCtrl()
{
	m_pRegion.reset();

	m_GDIpInitializer.Deinitialize();
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::OnDraw - Drawing function

void CPGLXCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	DoSuperclassPaint(pdc, rcBounds);

	if (!m_pRegion)
	{
//		CGdiObject* pOldObject=pdc->SelectStockObject(WHITE_BRUSH);
//		CRgn rgn;
//		rgn.CreateRectRgn(rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom);
//		VERIFY(pdc->PaintRgn( &rgn ));
//		pdc->SelectObject(pOldObject);
		return;
	} 

	// setting interface...
	m_GDIpInterface.SetMainBoundingBox(0,0,rcBounds.Width(),rcBounds.Height());
	m_pRegion->SetViewport(0,0,rcBounds.Width(),rcBounds.Height());

	Gdiplus::Graphics graphics(pdc->m_hDC);

	Gdiplus::Bitmap MemBitmap((INT)floor(m_GDIpInterface.GetMainBBWidth()), (INT)floor(m_GDIpInterface.GetMainBBHeight()));
	Gdiplus::Bitmap* m_pMemBitmap = &MemBitmap;

	ASSERT(m_pMemBitmap);
	ASSERT(m_pMemBitmap->GetLastStatus() == Gdiplus::Ok);

	Gdiplus::Graphics* pMemGraphics = Gdiplus::Graphics::FromImage(m_pMemBitmap);	
	m_GDIpInterface.SetGraphics(pMemGraphics);

	// setting size
	m_GDIpInterface.BeginPaint(pdc->GetSafeHdc());

	if (m_bAutoZoom)
	{
		m_pRegion->ZoomAll(m_GDIpInterface, TRUE);
	}
	else
	{
		m_pRegion->RefreshView(m_GDIpInterface, TRUE, FALSE);
	}

	m_pRegion->PlotGfx(m_GDIpInterface);
	m_GDIpInterface.EndPaint();
	
	// Draw the image.
	graphics.DrawImage(m_pMemBitmap, 0,0);
	
	delete pMemGraphics;
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::DoPropExchange - Persistence support

void CPGLXCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);


	PX_String(pPX, _T("XMLString"), m_sXMLString, _T(""));
	PX_String(pPX, _T("XMLURL"), m_sXMLURL, _T(""));
	PX_String(pPX, _T("XMLFile"), m_sXMLFile, _T(""));
	PX_Bool(pPX, _T("AutoZoom"), m_bAutoZoom, TRUE);

	if (pPX->IsLoading())
	{
		if (!m_sXMLString.IsEmpty())
		{
			OnXMLStringChanged();
		}
		else if ( ! m_sXMLURL.IsEmpty() )
		{
			OnXMLURLChanged();
		}
		else if ( ! m_sXMLFile.IsEmpty() )
		{
			OnXMLFileChanged();
		}
	}
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::GetControlFlags -
// Flags to customize MFC's implementation of ActiveX controls.
//
// For information on using these flags, please see MFC technical note
// #nnn, "Optimizing an ActiveX Control".
DWORD CPGLXCtrl::GetControlFlags()
{
	DWORD dwFlags = COleControl::GetControlFlags();


	// The control can activate without creating a window.
	// TODO: when writing the control's message handlers, avoid using
	//		the m_hWnd member variable without first checking that its
	//		value is non-NULL.
	dwFlags |= windowlessActivate;
	dwFlags |= canOptimizeDraw;
	return dwFlags;
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::OnResetState - Reset control to default state

void CPGLXCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	m_pRegion.reset();
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::AboutBox - Display an "About" box to the user

void CPGLXCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_PGLX);
	dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::PreCreateWindow - Modify parameters for CreateWindowEx

BOOL CPGLXCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.lpszClass = _T("STATIC");
	return COleControl::PreCreateWindow(cs);
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::IsSubclassedControl - This is a subclassed control

BOOL CPGLXCtrl::IsSubclassedControl()
{
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl::OnOcmCommand - Handle command messages

LRESULT CPGLXCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN32
	WORD wNotifyCode = HIWORD(wParam);
#else
	WORD wNotifyCode = HIWORD(lParam);
#endif

	// TODO: Switch on wNotifyCode here.

	return 0;
}


/////////////////////////////////////////////////////////////////////////////
// CPGLXCtrl message handlers

void CPGLXCtrl::OnXMLFileChanged() 
{
	TRY
	{
	   CFile file;

	   if (file.Open(m_sXMLFile, CFile::modeRead))
	   {
			UINT length=(UINT)file.GetLength();
			file.Read(m_sXMLString.GetBuffer(length), length);
			m_sXMLString.ReleaseBuffer();
	
			OnXMLStringChanged();
	   }
	}
	CATCH( CFileException, e )
	{
	}
	END_CATCH

	SetModifiedFlag();
	InvalidateRect(NULL,FALSE);
}

void CPGLXCtrl::OnXMLStringChanged() 
{
	if (!m_sXMLString.IsEmpty())
	{
		// Creating graph if needed
		if (!m_pRegion)
		{
			m_pRegion = CPGLRegionPtr(new CPGLRegion);
			if (!m_pRegion)
				return;
		}

		m_script.SetCR( m_pRegion->GetID());

		// creating xml marker...
		CPGLArchive ar(m_pRegion, &m_GDIpInterface);
		if(!ar.LoadString(m_sXMLString))
		{
			AfxMessageBox(_T("PGLX could not load XML data."));
		}
	}

	SetModifiedFlag();
	InvalidateRect(NULL,FALSE);
}

void CPGLXCtrl::OnXMLURLChanged() 
{
	// loading...
	CStdioFile* pFile;

	TRY
	{
		CInternetSession session;
		pFile=session.OpenURL(m_sXMLURL);

		if (pFile)
		{
			UINT length= (UINT)pFile->GetLength();
			pFile->Read(m_sXMLString.GetBuffer(length), length);
			m_sXMLString.ReleaseBuffer();
	
			OnXMLStringChanged();
		}
	
		session.Close();
	}
	CATCH(CInternetException,e)
	{
	}
	END_CATCH

	SetModifiedFlag();
	InvalidateRect(NULL,FALSE);
}

void CPGLXCtrl::OnAutoZoomChanged()
{
	SetModifiedFlag();
}

long CPGLXCtrl::Figure() 
{
	return m_script.Figure();
}


BOOL CPGLXCtrl::SetCR(long lRegionID) 
{
	return m_script.SetCR(lRegionID);
}

void CPGLXCtrl::CloseAllFigures() 
{
	m_script.CloseAllFigures();
}

void CPGLXCtrl::Divide(long lRegionID, short nRows, short nCols) 
{
	m_script.Divide(lRegionID, nRows, nCols);
}

BSTR CPGLXCtrl::Get(long lObjectID, const VARIANT FAR& szProp) 
{
	CString strResult;

	return strResult.AllocSysString();
}

long CPGLXCtrl::GetCR() 
{
	return m_script.GetCR();
}

BSTR CPGLXCtrl::GetHelp(long lObjectID) 
{
	// TODO: Add your dispatch handler code here
	CString str;
	m_script.GetHelp( lObjectID, str);

	CString strResult(str);
	return strResult.AllocSysString();
}

long CPGLXCtrl::GetParent(long lObjectID) 
{
	return m_script.GetParent(lObjectID);
}

CPGLVectorFPtr CPGLXCtrl::SafeArrayToPGLData(const VARIANT FAR& sa)
{
	CPGLSafeArray a(sa, false);
	if (FAILED(a.GetLastHRESULT()))
		return CPGLVectorFPtr();

	const size_t n= a.size();
	CPGLVectorFPtr pV(new CPGLVectorF( n ));
	std::vector<float>& v=pV->GetV();
	for (size_t i=0;i<n;i++)
		v[i]=a[i];

	return pV;
}

long CPGLXCtrl::Histogram(long lRegionID, const VARIANT FAR& saValues, const VARIANT FAR& szFormat) 
{
	_bstr_t str( szFormat );
	return m_script.Histogram( lRegionID,SafeArrayToPGLData(saValues), (LPCTSTR)str);
}

long CPGLXCtrl::Plot(long lRegionID, const VARIANT FAR& saX, const VARIANT FAR& saY, const VARIANT FAR& szFormat) 
{
	_bstr_t str( szFormat );	
	return m_script.Plot( lRegionID, SafeArrayToPGLData(saX), SafeArrayToPGLData(saY), (LPCTSTR)str);
}


long CPGLXCtrl::Legend(long lRegionID, const VARIANT FAR& szState) 
{
	return m_script.Legend(lRegionID);
}

long CPGLXCtrl::PlotLOD(long lRegionID, const VARIANT FAR& saX, const VARIANT FAR& saY, float fCompRatio, const VARIANT FAR& szFormat) 
{
	_bstr_t str( szFormat );	
	return m_script.PlotLOD( lRegionID, SafeArrayToPGLData(saX), SafeArrayToPGLData(saY), fCompRatio, (LPCTSTR)str);
}

void CPGLXCtrl::Title(long lRegionID, const VARIANT FAR& szText) 
{
	m_script.Title(lRegionID, _bstr_t(szText) );
}

void CPGLXCtrl::XLabel(long lRegionID, const VARIANT FAR& szText) 
{
	m_script.BottomLabel(lRegionID, _bstr_t(szText) );
}

void CPGLXCtrl::YLabel(long lRegionID, const VARIANT FAR& szText) 
{
	m_script.LeftLabel(lRegionID, _bstr_t(szText) );
}

BOOL CPGLXCtrl::RenderToFile(long lRegionID, const VARIANT FAR& szFileName, const VARIANT FAR& szFormat) 
{
	return 	m_script.RenderToFile(lRegionID, _bstr_t(szFileName), _bstr_t(szFormat) );
}

long CPGLXCtrl::Region()
{
	return m_script.Region();
}

long CPGLXCtrl::GetChild(long lRegionID, long lIndex) 
{
	return m_script.GetChild(lRegionID, lIndex);
}

void CPGLXCtrl::ClearRegion(long lRegionID) 
{
}

void CPGLXCtrl::Set(long lObjectID, const VARIANT FAR& szPropAndValues) 
{
	m_script.Set(lObjectID, _bstr_t( szPropAndValues) );
}

void CPGLXCtrl::OutOfChild() 
{
	m_script.OutOfChild();
}

BOOL CPGLXCtrl::SaveToXml(long lRegionID, const VARIANT FAR& szFileName, short bZipped) 
{
	return m_script.SaveToXML( lRegionID, _bstr_t(szFileName), bZipped);
}

BOOL CPGLXCtrl::LoadFromXML(long lRegionID, const VARIANT FAR& szFileName) 
{
	return m_script.LoadFromXML( lRegionID, _bstr_t(szFileName));
}

long CPGLXCtrl::Stock(long lRegionID, const VARIANT FAR& saOpen, const VARIANT FAR& saHigh, const VARIANT FAR& saLow, const VARIANT FAR& saClose, const VARIANT FAR& szFormat) 
{
	_bstr_t str( szFormat );	
	return 0;
}

long CPGLXCtrl::Scatter(long lRegionID, const VARIANT FAR& saX, const VARIANT FAR& saY, const VARIANT FAR& saValues, const VARIANT FAR& szFormat) 
{
	_bstr_t str( szFormat );	
	return m_script.Scatter( lRegionID, SafeArrayToPGLData(saX), SafeArrayToPGLData(saY), SafeArrayToPGLData(saValues), (LPCTSTR)str);
}

long CPGLXCtrl::ErrorBar(long lRegionID, const VARIANT FAR& saX, const VARIANT FAR& saY, const VARIANT FAR& saErrorUp, const VARIANT FAR& saErrorDown, const VARIANT FAR& szFormat) 
{
 	_bstr_t str( szFormat );	
 	return m_script.ErrorBar( lRegionID, SafeArrayToPGLData(saX), SafeArrayToPGLData(saY), SafeArrayToPGLData(saErrorUp), SafeArrayToPGLData(saErrorDown), (LPCTSTR)str);
}
